home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 6 / The Arsenal Files 6 (Arsenal Computer).ISO / prg_gen / inter49e.zip / INTLIST.E < prev    next >
Text File  |  1995-10-29  |  40KB  |  1,378 lines

  1. /****************************************************************/
  2. /*    EEL code file for editing the Interrupt List        */
  3. /*                                */
  4. /*    Written by Ralf Brown                    */
  5. /*    LastEdit:  29 Oct 95                    */
  6. /*                                */
  7. /*  This EEL file adds the following keybindings:        */
  8. /*    Shf-Alt-B add another BUG: to the current entry           */
  9. /*    Shf-Alt-D add a Desc: section to the current entry    */
  10. /*    Sft-Alt-I add an InstallCheck: section to current entry    */
  11. /*    Shf-Alt-R add a Range: section to the current entry       */
  12. /*    Shf-Alt-S add a Size: section to the current entry    */
  13. /*    Alt-I    add an Index: section to the current entry    */
  14. /*        add another Index: line if already on Index:    */
  15. /*      Alt-N   add a new note to current entry or data struct  */
  16. /*      Alt-P   add a Program: section to the current entry     */
  17. /*      Alt-R   insert Return: at start of line                 */
  18. /*    Alt-S    insert SeeAlso: at start of line        */
  19. /*    F11    insert a blank separator line            */
  20. /*    ^F11    create Format of: header            */
  21. /*    Shf-F11    create Values for: header            */
  22. /*    Alt-F11 create Call with: header            */
  23. /*    Alt-F12 create Bitfield for: header            */
  24. /*    F12    add the interrupt number to the separator line    */
  25. /*        preceding the current entry            */
  26. /*    ^F12    jump to a specified entry            */
  27. /*                                */
  28. /*  It adds the following unbound commands:                */
  29. /*      renumber-tables                            */
  30. /*    make-distribution                    */
  31. /*                                */ 
  32. /*  Other:                            */
  33. /*    adds intlist-mode for .LST and .1ST files        */
  34. /*    switches current buffer into intlist-mode on loading    */
  35. /*      maintains a table counter which is inserted each time   */
  36. /*        a table is created in the text                */
  37. /****************************************************************/
  38.  
  39. #include "eel.h"
  40.  
  41. keytable intlist_tab ;            /* key table for IntList mode */
  42.  
  43. /* on repeated F12, how often to display number of entries processed */
  44. /* for fast 386, every 100; for a Pentium, at least 300 or the message */
  45. /* line will lag way behind the actual progress */
  46. #define NUMBER_INT_PROGRESS_INTERVAL 500
  47.  
  48. /*=============================================================*/
  49. /*    Global Variables                           */
  50. /*=============================================================*/
  51.  
  52. char size_section[] = "Size:\t" ;
  53. char return_section[] = "Return: " ;
  54. char install_section[] = " InstallCheck: " ;
  55. char program_section[] = "Program: " ;
  56. char desc_section[] = "Desc:\t" ;
  57. char range_section[] = "Range:\t" ;
  58. char notes_section[] = "Notes*:\t" ;
  59. char bugs_section[] = "BUGS*:\t" ;
  60. char seealso_section[] = "SeeAlso: " ;
  61. char index_section[] = "Index:\t" ;
  62.  
  63. char table_ID_letters[] = "0123456789CFMP" ;
  64.  
  65. char *(section_order[11]) ;
  66. char *(list_files[7]) ;
  67.  
  68. when_loading()
  69. {
  70.    /* list the sections of an entry in the order they should appear (if */
  71.    /* present at all) */
  72.    section_order[0] = size_section ;
  73.    section_order[1] = return_section ;
  74.    section_order[2] = install_section ;
  75.    section_order[3] = program_section ;
  76.    section_order[4] = desc_section ;
  77.    section_order[5] = range_section ;
  78.    section_order[6] = notes_section ;
  79.    section_order[7] = bugs_section ;
  80.    section_order[8] = seealso_section ;
  81.    section_order[9] = index_section ;
  82.    section_order[10] = NULL ;
  83.    /* list the files comprising the full interrupt list */
  84.    list_files[0] = "cmos.lst" ;
  85.    list_files[1] = "farcall.lst" ;
  86.    list_files[2] = "memory.lst" ;
  87.    list_files[3] = "ports.lst" ;
  88.    list_files[4] = "interrup.lst" ;
  89.    list_files[5] = "tables.lst" ;
  90.    list_files[6] = NULL ;
  91. }
  92.  
  93. /*=============================================================*/
  94. /*    Buffer-specific variables                       */
  95. /*=============================================================*/
  96.  
  97. buffer spot table_counter ;
  98.  
  99. /*=============================================================*/
  100. /*=============================================================*/
  101.  
  102. int empty_line()
  103. {
  104.    return (character(point-1) == '\n' && character(point) == '\n') ;
  105. }
  106.  
  107. /*=============================================================*/
  108. /*=============================================================*/
  109.  
  110. int is_separator_line()
  111. {
  112.    return (empty_line() || parse_string(1,"--------",NULL)) ;
  113. }
  114.  
  115. /*=============================================================*/
  116. /* search in the specified direction (1 = forward, -1 = back)  */
  117. /* for the next entry separator line                   */
  118. /*=============================================================*/
  119.  
  120. int to_separator_line(dir)
  121. int dir ;
  122. {
  123.    nl_reverse() ;
  124.    return search(dir,"\n--------") ;
  125. }
  126.  
  127. /*=============================================================*/
  128. /* move to the location where the specified section of an      */
  129. /* entry begins (if present) or should begin (if not)           */
  130. /*=============================================================*/
  131.  
  132. int to_section_start(section)
  133. char *section ;
  134. {
  135.    int i, j, len ;
  136.  
  137.    for (i = 0 ; section_order[i] ; i++)
  138.       if (strcmp(section,section_order[i]) == 0)
  139.      break ;
  140.    if (section_order[i])
  141.       {
  142.       while (!is_separator_line())
  143.      {
  144.      for (j = i ; section_order[j] ; j++)
  145.         if (parse_string(1,section_order[j],NULL))
  146.            {
  147.            if ((len = parse_string(1,section,NULL)) != 0)
  148.           {
  149.           point += len ;
  150.           return 1 ;    /* section already exists */
  151.           }
  152.            return 0 ;    /* section nonexistent, but found position */
  153.            }
  154.      if (!nl_forward())
  155.         break ;
  156.      }
  157.       return 0 ;    /* section does not yet exist */
  158.       }
  159.    else
  160.       return 0 ;    /* section not found */
  161. }
  162.  
  163. /*=============================================================*/
  164. /*=============================================================*/
  165.  
  166. int make_section(section,start_entry,name)
  167. char *section, *name ;
  168. int start_entry ;
  169. {
  170.    int start = point ;
  171.  
  172.    if (start_entry)
  173.       {
  174.       if (!to_separator_line(-1))  /* find previous separator line */
  175.      {
  176.      point = start ;
  177.      say("Not in an interrupt entry") ;
  178.      return 0 ;
  179.      }
  180.       }
  181.    else
  182.       {
  183.       to_begin_line() ;
  184.       while (!empty_line() && !parse_string(1,"\n--------",NULL))
  185.      if (!nl_reverse())
  186.         break ;
  187.       }
  188.    point++ ;                 /* skip the newline */
  189.    nl_forward() ;             /* advance to first line of entry */
  190.    if (!to_section_start(section))
  191.       {
  192.       if (name)
  193.      stuff(name) ;
  194.       else
  195.      stuff(section) ;
  196.       stuff("\n") ;
  197.       point-- ;              /* back up over inserted newline */
  198.       return 1 ;
  199.       }
  200.    else
  201.       return 0 ;
  202.    return 2 ;  /* just in case */
  203. }
  204.  
  205. /*=============================================================*/
  206. /*=============================================================*/
  207.  
  208. int pluralize_section(plural)
  209. char plural ;
  210. {
  211.    point -= 3 ;
  212.    if (curchar() != plural)        /* already plural ? */
  213.       {
  214.       point++ ;
  215.       insert(plural) ;
  216.       }
  217.    nl_forward() ;
  218.    while (!is_separator_line() && parse_string(1,"[ \t]",NULL))
  219.       nl_forward() ;
  220.    stuff("\t\n") ;
  221.    point-- ;
  222. }
  223.  
  224. /*=============================================================*/
  225. /* Add "SeeAlso: " to the beginning of the current line unless */
  226. /* it is already present                       */
  227. /*=============================================================*/
  228.  
  229. command see_also() on intlist_tab[ALT('s')]
  230. {
  231.    to_begin_line() ;
  232.    if (parse_string(1,"SeeAlso: ",NULL) == 0)
  233.       stuff("SeeAlso: ") ;
  234.    else
  235.       {
  236.       nl_forward() ;
  237.       stuff("SeeAlso: \n") ;
  238.       point-- ;
  239.       }
  240. }
  241.  
  242. /*=============================================================*/
  243. /* Add a Desc: section if the current entry does not already   */
  244. /* have one; if there is already a Desc: section, move to the  */
  245. /* start of it                               */
  246. /*=============================================================*/
  247.  
  248. command desc() on intlist_tab[ALT('D')]
  249. {
  250.    make_section(desc_section,1,NULL) ;
  251. }
  252.  
  253. /*=============================================================*/
  254. /* Add a InstallCheck: section if the current entry does not   */
  255. /* already have one; if there is already a InstallCheck:       */
  256. /* section, move to the start of it                   */
  257. /*=============================================================*/
  258.  
  259. command instcheck() on intlist_tab[ALT('I')]
  260. {
  261.    make_section(install_section,1,NULL) ;
  262. }
  263.  
  264. /*=============================================================*/
  265. /* Add a Range: section if the current entry does not already  */
  266. /* have one; if there is already a Range: section, move to the */
  267. /* start of it                               */
  268. /*=============================================================*/
  269.  
  270. command range() on intlist_tab[ALT('R')]
  271. {
  272.    make_section(range_section,1,NULL) ;
  273. }
  274.  
  275. /*=============================================================*/
  276. /* Add a Size: section if the current entry does not already   */
  277. /* have one; if there is already a Size: section, move to the  */
  278. /* start of it                               */
  279. /*=============================================================*/
  280.  
  281. command memsize() on intlist_tab[ALT('S')]
  282. {
  283.    make_section(size_section,1,NULL) ;
  284. }
  285.  
  286. /*=============================================================*/
  287. /* Add a "Program: " section to the current entry if it does   */
  288. /* not have one; otherwise, move to the beginning of the       */
  289. /* Program: section                           */
  290. /*=============================================================*/
  291.  
  292. command program() on intlist_tab[ALT('p')]
  293. {
  294.    make_section(program_section,1,NULL) ;
  295. }
  296.  
  297. /*=============================================================*/
  298. /* Add an "Index: " section to the current entry if it does    */
  299. /* not have one; otherwise, move to the beginning of the       */
  300. /* Index: section                           */
  301. /*=============================================================*/
  302.  
  303. command add_index() on intlist_tab[ALT('i')]
  304. {
  305.    to_begin_line() ;
  306.    if (parse_string(1,"Index:",NULL))
  307.       {
  308.       while (parse_string(1,"Index:",NULL))
  309.      nl_forward() ;
  310.       stuff("Index:\t\n") ;
  311.       point-- ;
  312.       }
  313.    else
  314.       make_section(index_section,1,NULL) ;
  315. }
  316.  
  317. /*=============================================================*/
  318. /*=============================================================*/
  319.  
  320. command bug() on intlist_tab[ALT('B')]
  321. {
  322.    if (!make_section(bugs_section,1,"BUG:\t"))
  323.       pluralize_section('S') ;
  324. }
  325.  
  326. /*=============================================================*/
  327. /* Add "Note: " section to the current entry; change an        */
  328. /* existing Note: to Notes: and position at end of Note:       */
  329. /* section.                               */
  330. /*=============================================================*/
  331.  
  332. command add_note() on intlist_tab[ALT('n')]
  333. {
  334.    if (!make_section(notes_section,0,"Note:\t"))
  335.       pluralize_section('s') ;
  336. }
  337.  
  338. /*=============================================================*/
  339. /* Insert "Return: " at the beginning of the current line, if  */
  340. /* not already present                           */
  341. /*=============================================================*/
  342.  
  343. command returns() on intlist_tab[ALT('r')]
  344. {
  345.    int start = point ;
  346.    
  347.    to_begin_line() ;
  348.    if (parse_string(1,return_section,NULL) == 0)
  349.       stuff(return_section) ;
  350.    else
  351.       point = start ;
  352. }
  353.  
  354. /*=============================================================*/
  355. /* insert a line of dashes prior to the current cursor line    */
  356. /*=============================================================*/
  357.  
  358. command separator_line() on intlist_tab[FKEY(11)]
  359. {
  360.    int i ;
  361.  
  362.    to_begin_line() ;
  363.    for (i = 0 ; i < 45 ; i++)
  364.       insert('-') ;
  365.    insert('\n') ;
  366. }
  367.  
  368. /*=============================================================*/
  369. /*=============================================================*/
  370.  
  371. void insert_table_counter()
  372. {
  373.    char counter[6] ;
  374.    save_var point = *table_counter + 3 ;
  375.  
  376.    /* increment that table counter */
  377.    while (curchar() >= '0')
  378.       {
  379.       if (curchar() < '9')
  380.      {
  381.      replace(point,curchar()+1) ;
  382.      break ;
  383.      }
  384.       else
  385.      {
  386.      replace(point,'0') ;
  387.      point-- ;
  388.      }
  389.       }
  390.    restore_vars() ;
  391.    /* and now insert the incremented value at point */
  392.    stuff("(Table ") ;
  393.    grab(*table_counter,*table_counter+4,counter) ;
  394.    stuff(counter) ;
  395.    stuff(")") ;
  396. }
  397.  
  398. /*=============================================================*/
  399. /* type the name of a structure, then invoke this function     */
  400. /* to create the "Format of X:" and "Offset Size Descr" lines  */
  401. /*=============================================================*/
  402.  
  403. command structure_header() on intlist_tab[FCTRL(11)]
  404. {
  405.    int start = point ;
  406.  
  407.    to_begin_line() ;
  408.    if (parse_string(1,"Format of ",NULL) == 0)
  409.       {
  410.       stuff("Format of ") ;
  411.       to_end_line() ;
  412.       stuff(":\nOffset\tSize\tDescription\t") ;
  413.       insert_table_counter() ;
  414.       stuff("\n 00h\t") ;
  415.       }
  416.    else
  417.       point = start ;
  418. }
  419.  
  420. /*=============================================================*/
  421. /* Turn the current line into the header for a "Values of"     */
  422. /* section                               */
  423. /*=============================================================*/
  424.  
  425. command value_header() on intlist_tab[FSHIFT(11)]
  426. {
  427.    int start = point ;
  428.    
  429.    to_begin_line() ;
  430.    if (parse_string(1,"Values for ",NULL) == 0)
  431.       {
  432.       insert_table_counter() ;
  433.       stuff("\nValues for ") ;
  434.       to_end_line() ;
  435.       stuff(":\n ") ;
  436.       }
  437.    else
  438.       point = start ;
  439. }
  440.  
  441. /*=============================================================*/
  442. /* Turn the current line into the header of a "Call with"      */
  443. /* section                               */
  444. /*=============================================================*/
  445.  
  446. command call_with_header() on intlist_tab[FALT(11)]
  447. {
  448.    int start = point ;
  449.    
  450.    to_begin_line() ;
  451.    if (parse_string(1,"Call ",NULL) == 0)
  452.       {
  453.       insert_table_counter() ;
  454.       stuff("\nCall ") ;
  455.       to_end_line() ;
  456.       if (character(point-1) != ' ')
  457.      stuff(" ") ;
  458.       stuff("with:\n") ;
  459.       }
  460.    else
  461.       point = start ;
  462. }
  463.  
  464. /*=============================================================*/
  465. /* Turn the current line into the header of a "Bitfield for"   */
  466. /* section                               */
  467. /*=============================================================*/
  468.  
  469. command bitfields_for_header() on intlist_tab[FALT(12)]
  470. {
  471.    int start = point ;
  472.    
  473.    to_begin_line() ;
  474.    if (parse_string(1,"Bitfields for ",NULL) == 0)
  475.       {
  476.       stuff("Bitfields for ") ;
  477.       to_end_line() ;
  478.       stuff(":\nBit(s)\tDescription\t") ;
  479.       insert_table_counter() ;
  480.       stuff("\n ") ;
  481.       }
  482.    else
  483.       point = start ;
  484. }
  485.  
  486. /*=============================================================*/
  487. /*=============================================================*/
  488.  
  489. char grab_int_entry_number(func_num)
  490. char *func_num ;
  491. {
  492.    int i ;
  493.    char c ;
  494.    
  495.    point += 4 ;                /* skip the "INT " */
  496.    func_num[0] = curchar() ;        /* grab the interrupt number */
  497.    point++ ;
  498.    func_num[1] = curchar() ;
  499.    nl_forward() ;            /* skip to second line of entry */
  500.    if (parse_string(1,"[ \t]*A[LHX][ \t]=[ \t][0-9A-F][0-9A-F]+h",NULL))
  501.       {
  502.       re_search(1,"[ \t]*A") ;
  503.       c = curchar() ;
  504.       point += 4 ;            /* skip ch and " = " */
  505.       if (c != 'L')
  506.      {
  507.      grab(point,point+((c=='X')?4:2),func_num+2) ;
  508.      point += ((c=='X')?4:2) ;
  509.      func_num[(c=='H')?4:6] = '-' ;    /* grab() stuck a NUL into the string */
  510.      }
  511.       else /* c == 'L' */
  512.      {
  513.      func_num[4] = curchar() ;
  514.      point++ ;
  515.      func_num[5] = curchar() ;
  516.      point ++ ;
  517.      }
  518.       point++ ;
  519.       if (parse_string(1,"[ \t]*subfn [0-9A-F][0-9A-F]+h",NULL))
  520.      {
  521.      re_search(1,"[ \t]*subfn ") ;
  522.      func_num[6] = 'S' ;
  523.      func_num[7] = 'F' ;
  524.      for (i = 0 ; i < 4 ; i++)
  525.         {
  526.         c = curchar() ;
  527.         if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
  528.            {
  529.            func_num[8+i] = c ;
  530.            point++ ;
  531.            }
  532.         else
  533.            break ;
  534.         }
  535.      }
  536.       nl_forward() ;            /* skip to third line of entry */
  537.       }
  538.    if (parse_string(1,"[ \t]*[BCDES][HILPSX] = [0-9A-F][0-9A-F]+h",NULL))
  539.       {
  540.       re_search(1,"[ \t]*") ;
  541.       func_num[6] = curchar() ;
  542.       point++ ;
  543.       func_num[7] = c = curchar() ;
  544.       point += 4 ;            /* skip curchar and " = " */
  545.       if (c == 'H' || c == 'L')
  546.      {
  547.      grab(point,point+2,func_num+8) ;
  548.      func_num[10] = '-' ;        /* grab() stuck a NUL into the string */
  549.      }
  550.       else /* c == 'X' || c == 'I' || c == 'P' || c == 'S' */
  551.      grab(point,point+4,func_num+8) ;
  552.       }
  553.    return 1 ;                /* successful and have func number */
  554. }
  555.  
  556. /*=============================================================*/
  557.  
  558. char grab_cmos_entry_number(func_num)
  559. char *func_num ;
  560. {
  561.    point += 5 ;                    /* skip the "CMOS " */
  562.    func_num[0] = 'R' ;            /* mark this as a CMOS RAM entry */
  563.    grab(point,point+4,func_num+1) ;
  564.    if (func_num[3] == 'h' && func_num[4] == '-')
  565.       grab(point+4,point+6,func_num+3) ;
  566.    else
  567.       {
  568.       func_num[3] = '-' ;
  569.       func_num[4] = '-' ;
  570.       }
  571.    func_num[5] = '-' ;            /* grab() stuck a NUL into string */
  572.    return 1 ;
  573. }
  574.  
  575. /*=============================================================*/
  576.  
  577. char grab_farcall_entry_number(func_num)
  578. char *func_num ;
  579. {
  580.    point += 5 ;                /* skip the "CALL " */
  581.    func_num[0] = '@' ;            /* mark this as a far call entry */
  582.    grab(point,point+4,func_num+1) ;    /* get segment of address */
  583.    grab(point+6,point+10,func_num+5) ;    /* get offset of address */
  584.    func_num[9] = '-' ;            /* grab() stuck a NUL into string */
  585.    return 1 ;
  586. }
  587.  
  588. /*=============================================================*/
  589.  
  590. char grab_memory_entry_number(func_num)
  591. char *func_num ;
  592. {
  593.    point += 4 ;                /* skip the "MEM " */
  594.    func_num[0] = 'M' ;                /* mark this as a memory loc entry */
  595.    grab(point,point+6,func_num+1) ;    /* get segment or high word of addr */
  596.    if (func_num[5] == 'h' && func_num[6] == ':') /* segmented address? */
  597.       grab(point+6,point+10,func_num+5) ;    /* get offset of address */
  598.    else
  599.       {
  600.       grab(point+6,point+8,func_num+7) ;/* get low word of the address */
  601.       func_num[0] = 'm' ;        /* indicate linear address */
  602.       }
  603.    func_num[9] = '-' ;            /* grab() stuck a NUL into string */
  604.    return 1 ;
  605. }
  606.  
  607. /*=============================================================*/
  608.  
  609. char grab_port_entry_number(func_num)
  610. char *func_num ;
  611. {
  612.    point += 5 ;                /* skip the "PORT " */
  613.    func_num[0] = 'P' ;            /* mark this as an I/O port entry */
  614.    grab(point,point+4,func_num+1) ;    /* get starting port number */
  615.    func_num[5] = '-' ;            /* grab() stuck a NUL into string */
  616.    if (character(point+4) == '-')
  617.       {
  618.       grab(point+5,point+9,func_num+5) ; /* get ending port number */
  619.       func_num[9] = '-' ;        /* grab() stuck a NUL into string */
  620.       }
  621.    return 1 ;
  622. }
  623.  
  624. /*=============================================================*/
  625.  
  626. char grab_entry_number(func_num)
  627. char *func_num ;
  628. {
  629.    strcpy(func_num,"------------") ;    /* 12 dashes */
  630.    point++ ;                /* go to first char of separator line */
  631.    nl_forward() ;            /* go to first line of entry */
  632.    if (parse_string(1,"INT ",NULL))    /* is it an interrupt entry? */
  633.       return grab_int_entry_number(func_num) ;
  634.    else if (parse_string(1,"CMOS ",NULL) != 0)
  635.       return grab_cmos_entry_number(func_num) ;
  636.    else if (parse_string(1,"CALL ",NULL) != 0)
  637.       return grab_farcall_entry_number(func_num) ;
  638.    else if (parse_string(1,"MEM ",NULL) != 0)
  639.       return grab_memory_entry_number(func_num) ;
  640.    else if (parse_string(1,"PORT ",NULL) != 0)
  641.       return grab_port_entry_number(func_num) ;
  642.    else
  643.       return 0 ;
  644. }
  645.  
  646. /*=============================================================*/
  647. /* Put the interrupt and function number into the separator    */
  648. /* line just above the intlist entry preceding the cursor pos  */
  649. /*=============================================================*/
  650.  
  651. int number_one_int()
  652. {
  653.    char func_num[13] ;            /* 2->int, 4->AX, 6->extra reg, NUL */
  654.    int oldpoint ;
  655.    
  656.    while (to_separator_line(-1))    /* find previous separator line */
  657.       {
  658.       oldpoint = point ;
  659.       if (grab_entry_number(func_num))    /* does it belong to an intlist entry? */
  660.      {                /*   if yes, success, else try again */
  661.      point = oldpoint + 11 ;    /* skip NL and first ten dashes */
  662.      delete(point,point+12) ;    /* replace 12 dashes by the function */
  663.      stuff(func_num) ;        /*   number and extra register */
  664.      point = oldpoint + 9 ;        /* back to category letter position */
  665.      return 1 ;
  666.      }
  667.       point = oldpoint ;
  668.       }
  669.    return 0 ;                /* if we get here, we failed */
  670. }
  671.  
  672. /*=============================================================*/
  673. /* Put the interrupt and function number into the separator    */
  674. /* line just above one or more intlist entries preceding the   */
  675. /* current cursor position, letting user know of progress      */
  676. /*=============================================================*/
  677.  
  678. command number_int() on intlist_tab[FKEY(12)]
  679. {
  680.    int i, hit_top = 0 ;
  681.    
  682.    for (i = 0 ; i < iter ; i++)
  683.       {
  684.       if (!number_one_int())
  685.      {
  686.      hit_top = 1 ;
  687.      say("No prior entry.") ;
  688.      break ;
  689.      }
  690.       if (((i+1) % NUMBER_INT_PROGRESS_INTERVAL) == 0)
  691.      say("%4d...",i+1) ;
  692.       }
  693.    if (iter > 1 && !hit_top)
  694.       say("Done.") ;
  695.    iter = 1 ;
  696. }
  697.  
  698. /*=============================================================*/
  699. /*=============================================================*/
  700.  
  701. int line_has_see_also()
  702. {
  703.    int len ;
  704.    
  705.    to_begin_line() ;
  706.    if ((len = parse_string(1,".*%([sS]ee ",NULL)) != 0)
  707.       {
  708.       point += len ;        /* go to start of cross-reference */
  709.       point += parse_string(1,"also ",NULL) ;
  710.       if (parse_string(1,"INT [0-9A-F]",NULL) ||
  711.       parse_string(1,"A[XHL] =",NULL)
  712.      )
  713.      {
  714.      point++ ;        /* move into reference */
  715.      return 1 ;
  716.      }
  717.       }
  718.    return 0 ;
  719. }
  720.  
  721. /*=============================================================*/
  722. /*=============================================================*/
  723.  
  724. int grab_int_reference(ref)
  725. char *ref ;
  726. {
  727.    int begin, start = point ;
  728.    
  729.    re_search(-1,"[, \t\n]") ;    /* backup to start of reference */
  730.    if (curchar() == '\n')    /* start of line? */
  731.       re_search(1,":[ \t]") ;    /* skip the SeeAlso: */
  732.    else if (character(point-1) == 'T' && character(point-2) == 'N')
  733.       point -= 3 ;
  734.    else
  735.       point++ ;            /* back to start of reference */
  736.    begin = point ;
  737.    re_search(1,"[,\n\"]") ;    /* find end of INT-spec */
  738.    point-- ;
  739.    if (curchar() == '\"')    /* extra string at end of INT-spec? */
  740.       {
  741.       point++ ;
  742.       re_search(1,"[\"\n]") ;    /* if yes, run to end of line or string */
  743.       }
  744.    grab(begin,point,ref) ;
  745.    point = start ;
  746.    return 0 ;
  747. }
  748.  
  749. /*=============================================================*/
  750. /*=============================================================*/
  751.  
  752. int parse_int_name(entry_name,id,extra_string)
  753. char *entry_name, *id, *extra_string ;
  754. {
  755.    int start = point ;
  756.    int i ;
  757.    char c, *last ;
  758.  
  759.    for (i = strlen(entry_name)-1 ; i >= 0 ; i--)
  760.       entry_name[i] = toupper(entry_name[i]) ;
  761.    strcpy(id,"------------") ;
  762.    if (strncmp(entry_name,"INT ",4) == 0)
  763.       {
  764.       id[0] = entry_name[4] ;
  765.       id[1] = entry_name[5] ;
  766.       entry_name += 6 ;
  767.       if (entry_name[0] == '/')
  768.      entry_name++ ;
  769.       }
  770.    else if (to_separator_line(-1))
  771.       {
  772.       id[0] = character(point+11) ;
  773.       id[1] = character(point+12) ;
  774.       }
  775.    point = start ;
  776.    c = entry_name[1] ;
  777.    if (entry_name[0] == 'A' && (c == 'X' || c == 'H' || c == 'L'))
  778.       {
  779.       entry_name += 2 ;
  780.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  781.      entry_name++ ;
  782.       if (entry_name[0] == '=')
  783.      entry_name++ ;
  784.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  785.      entry_name++ ;
  786.       if (c != 'L')
  787.      {
  788.          id[2] = entry_name[0] ;
  789.          id[3] = entry_name[1] ;
  790.      }
  791.       if (c == 'X')
  792.      {
  793.      id[4] = entry_name[2] ;
  794.      id[5] = entry_name[3] ;
  795.      entry_name += 4 ;
  796.      }
  797.       else
  798.      {
  799.      if (c == 'L')
  800.         {
  801.         id[2] = entry_name[0] ;
  802.         id[3] = entry_name[1] ;
  803.         }
  804.      entry_name += 2 ;
  805.      }
  806.       if (entry_name[0] == 'H')
  807.      entry_name++ ;
  808.       if (entry_name[0] == '/')
  809.      entry_name++ ;
  810.       }
  811.    if (index("ABCDES",entry_name[0]) && index("HILPSXF",entry_name[1]))
  812.       {
  813.       id[6] = entry_name[0] ;
  814.       c = id[7] = entry_name[1] ;
  815.       entry_name += 2 ;
  816.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  817.      entry_name++ ;
  818.       if (entry_name[0] == '=')
  819.      entry_name++ ;
  820.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  821.      entry_name++ ;
  822.       id[8] = entry_name[0] ;
  823.       id[9] = entry_name[1] ;
  824.       if (c != 'H' && c != 'L' && (c != 'F' || entry_name[2] != 'h'))
  825.      {
  826.      id[10] = entry_name[2] ;
  827.      id[11] = entry_name[3] ;
  828.      entry_name += 4 ;
  829.      }
  830.       else
  831.      entry_name += 2 ;
  832.       if (entry_name[0] == 'H')
  833.      entry_name++ ;
  834.       if (entry_name[0] == '/')
  835.      entry_name++ ;
  836.       }
  837.    if (entry_name[0] == '\"')
  838.       {
  839.       entry_name++ ;
  840.       strcpy(extra_string,entry_name) ;
  841.       last = index(extra_string,'\"') ;
  842.       if (last)
  843.      *last = '\0' ;
  844.       }
  845.    else
  846.       extra_string[0] = '\0' ;
  847.    return 0 ;
  848. }
  849.  
  850. /*=============================================================*/
  851. /*=============================================================*/
  852.  
  853. int hex2_to_int(c1,c2)
  854. char c1, c2 ;
  855. {
  856.    if (c1 >= '0' && c1 <= '9')
  857.       c1 -= '0' ;
  858.    else if (c1 >= 'A' && c1 <= 'F')
  859.       c1 = c1 - 'A' + 10 ;
  860.    else if (c1 >= 'a' && c1 <= 'f')
  861.       c1 = c1 - 'a' + 10 ;
  862.    else
  863.       return -1 ;
  864.    if (c2 >= '0' && c2 <= '9')
  865.       c2 -= '0' ;
  866.    else if (c2 >= 'A' && c2 <= 'F')
  867.       c2 = c2 - 'A' + 10 ;
  868.    else if (c2 >= 'a' && c2 <= 'f')
  869.       c2 = c2 - 'a' + 10 ;
  870.    else
  871.       return -1 ;
  872.    return 16*c1 + c2 ;
  873. }
  874.  
  875. /*=============================================================*/
  876. /*=============================================================*/
  877.  
  878. char hex_digit(val)
  879. int val ;
  880. {
  881.    if (val < 0)
  882.       return '-' ;
  883.    else
  884.       return (val > 9) ? ('A' + val - 10) : ('0' + val) ;
  885. }
  886.  
  887. /*=============================================================*/
  888. /*=============================================================*/
  889.  
  890. int scan_for_entry(entry,extra_str,first_entry)
  891. char *entry, *extra_str ;
  892. int *first_entry ;
  893. {
  894.    int ah, al, t1, t2, match, found ;
  895.    char buf[7] ;
  896.  
  897.    if (extra_str) extra_str = 0 ;  /* for now, to avoid compiler warning */
  898.    *first_entry = 0 ;
  899.    ah = hex2_to_int(entry[2],entry[3]) ;
  900.    while (1)
  901.       {
  902.       if (!to_separator_line(1))
  903.      return 0 ;    /* failed if hit end of file */
  904.       if (character(point+1) != entry[0] || character(point+2) != entry[1])
  905.      return 0 ;    /* failed if no longer on same interrupt */
  906.       t1 = hex2_to_int(character(point+3),character(point+4)) ;
  907.       if (t1 == ah)
  908.      break ;
  909.       else if (t1 > ah)
  910.      {
  911.      to_begin_line() ;
  912.      *first_entry = point ;
  913.      return 0 ;    /* no such entry */
  914.      }
  915.       }
  916.    nl_reverse() ;
  917.    *first_entry = point ;
  918.    found = 0 ;
  919.    al = hex2_to_int(entry[4],entry[5]) ;
  920.    while (1)
  921.       {
  922.       if (!to_separator_line(1))
  923.      return 0 ;    /* failed if hit end of file */
  924.       if (character(point+1) != entry[0] || character(point+2) != entry[1])
  925.      return 0 ;    /* failed if no longer on same interrupt */
  926.       t1 = hex2_to_int(character(point+3),character(point+4)) ;
  927.       if (t1 != ah)
  928.      return 0 ;    /* failed if no longer on same INT/AH combo */
  929.       t2 = hex2_to_int(character(point+5),character(point+6)) ;
  930.       if (t2 == al)
  931.      {
  932.      if (!found)
  933.         {
  934.         found = 1 ;
  935.         *first_entry = point ;
  936.         }
  937.      if (entry[6] != '-')
  938.         {
  939.         grab(point+7,point+12,buf) ;
  940.         match = strncmp(buf,entry+6,6) ;
  941.         if (match == 0)
  942.            {
  943.            *first_entry = point ;
  944.            break ;
  945.            }
  946.         else if (match > 0)
  947.            return 0 ;    /* no exact match, but return a partial match */
  948.         }
  949.      else
  950.         break ;
  951.      }
  952.       else if (t2 > al)
  953.      {
  954.      if (found)
  955.         break ;
  956.      else
  957.         {
  958.         to_begin_line() ;
  959.         *first_entry = point ;
  960.         return 0 ;    /* no such entry */
  961.         }
  962.      }
  963.       }
  964.    point = *first_entry ;    /* back to first matching entry */
  965.    
  966.    
  967.    return 1 ;            /* we were successful */
  968. }
  969.  
  970. /*=============================================================*/
  971. /*=============================================================*/
  972.  
  973. int goto_entry(entry_name)
  974. char *entry_name ;
  975. {
  976.    char int_id[13], extra_string[60] ;
  977.    int start = point, first_entry ;
  978.    int int_num, curr_int ;
  979.    char search_str[22] ;
  980.    
  981.    parse_int_name(entry_name,int_id,extra_string) ;
  982.    int_num = hex2_to_int(int_id[0],int_id[1]) ;
  983.    if (to_separator_line(-1))
  984.       {
  985.       if (character(point+11) == '-')
  986.      curr_int = -1 ;
  987.       else
  988.      curr_int = hex2_to_int(character(point+11),character(point+12)) ;
  989.       if (int_num <= 0)
  990.      point = 0 ;        /* go to top of file */
  991.       else
  992.      {
  993.      if (curr_int < 0)
  994.         point = 0 ;        /* go to top of file */
  995.      strcpy(search_str,"----------") ;
  996.      search_str[10] = hex_digit((int_num-1) / 16) ;
  997.      search_str[11] = hex_digit((int_num-1) % 16) ;
  998.      search_str[12] = '\0' ;
  999.      search( (int_num<=curr_int)?-1:1, search_str) ;
  1000.      to_begin_line() ;
  1001.      }
  1002.       }
  1003.    else
  1004.       point = 0 ;
  1005.    if (!scan_for_entry(int_id,extra_string,&first_entry))
  1006.       {
  1007.       say("%s not found.",entry_name) ;
  1008.       if (first_entry)
  1009.      {
  1010.      mark = start ;
  1011.      point = first_entry ;
  1012.      }
  1013.       else
  1014.      point = start ;
  1015.       }
  1016.    if (has_arg)
  1017.      iter = 1 ;                /* don't search repeatedly */
  1018.    return 0 ;
  1019. }
  1020.  
  1021. /*=============================================================*/
  1022. /*=============================================================*/
  1023.  
  1024. command goto_int() on intlist_tab[FCTRL(12)]
  1025. {
  1026.    char entry_name[60], def_entry[60] ;
  1027.    int start = point ;
  1028.  
  1029.    to_begin_line() ;
  1030.    if (parse_string(1,"SeeAlso: ",NULL) != 0)
  1031.       {
  1032.       point += 9 ;        /* skip the SeeAlso: */
  1033.       if (point < start)    /* if we were originally to the right of     */
  1034.      point = start ;    /* current position, go back to original pos */
  1035.       grab_int_reference(def_entry) ;
  1036.       get_strdef(entry_name,"Goto Interrupt",def_entry) ;
  1037.       }
  1038.    else if (line_has_see_also())
  1039.       {
  1040.       grab_int_reference(def_entry) ;
  1041.       get_strdef(entry_name,"Goto Interrupt",def_entry) ;
  1042.       }
  1043.    else
  1044.       get_string(entry_name,"Goto Interrupt: ") ;
  1045.    point = start ;
  1046.    goto_entry(entry_name) ;
  1047.    if (has_arg)
  1048.       iter = 1 ;
  1049. }
  1050.  
  1051. /*=============================================================*/
  1052. /*=============================================================*/
  1053.  
  1054. void maybe_append_table_number()
  1055. {
  1056.    if (parse_string(1,".*\t%(Table ",0) == 0)
  1057.       {
  1058.       int matchsize ;
  1059.       /* if the pattern didn't match, there is no table number, */
  1060.       /* so add it */
  1061.       to_end_line() ;
  1062.       matchsize = parse_string(-1,"[ \t]+",0) ;
  1063.       if (matchsize)
  1064.      delete(point-matchsize,point) ;
  1065.       stuff("\t") ;
  1066.       insert_table_counter() ;
  1067.       }
  1068. }
  1069.  
  1070. /*=============================================================*/
  1071. /*=============================================================*/
  1072.  
  1073. void fix_unnumbered_tables()
  1074. {
  1075.    spot start = alloc_spot(1) ;
  1076.    
  1077.    *start = point ;
  1078.    point = 0 ;
  1079.    while (search(1,"\n\n"))
  1080.       {
  1081.       switch(curchar())
  1082.      {
  1083.      case 'C':
  1084.         if (parse_string(1,"Call ") != 0)
  1085.            {
  1086.            /* we got Call..., we know it doesn't have a table number */
  1087.            insert_table_counter() ;
  1088.            stuff("\n") ;
  1089.            }
  1090.         break ;
  1091.      case 'V':
  1092.         if (parse_string(1,"Values ") != 0)
  1093.            {
  1094.            /* we know this Values... doesn't have a table number */
  1095.            insert_table_counter() ;
  1096.            stuff("\n") ;
  1097.            }
  1098.         break ;
  1099.      case 'B':
  1100.         if (parse_string(1,"Bitfields ",0) == 0)
  1101.            break ;
  1102.         nl_forward() ;    /* skip to start of next line */
  1103.         maybe_append_table_number() ;
  1104.         break ;
  1105.      case 'F':
  1106.         if (parse_string(1,"Format ",0) == 0)
  1107.            break ;
  1108.         nl_forward() ;    /* skip to start of next line */
  1109.         maybe_append_table_number() ;
  1110.         break ;
  1111.      default:
  1112.         /* not a table header, so ignore it */
  1113.         break ;
  1114.      }
  1115.       }
  1116.    point = *start ;
  1117.    free_spot(start) ;
  1118. }
  1119.  
  1120. /*=============================================================*/
  1121. /*=============================================================*/
  1122.  
  1123. short *gather_table_numbers(new_numbers)
  1124. short *new_numbers ;
  1125. {
  1126.    int tcount[6] ;
  1127.    char counter[5] ;
  1128.    int old_number ;
  1129.    int table_type ;
  1130.    spot start = alloc_spot(1) ;
  1131.    save_var case_fold = 0 ;
  1132.    
  1133.    tcount[0] = tcount[1] = tcount[2] = tcount[3] = tcount[4] = tcount[5] = 0 ;
  1134.    *start = point ;
  1135.    point = 0 ;
  1136.    while (search(1,"(Table "))
  1137.       {
  1138.       char *tbl ;
  1139.       int table_offset ;
  1140.       grab(point,point+4,counter) ;
  1141.       tbl = index(table_ID_letters,counter[0]) ;
  1142.       if (tbl)
  1143.      table_offset = (tbl-table_ID_letters) ;
  1144.       else
  1145.      table_offset = 0 ;
  1146.       old_number = strtoi(counter+1,10) + 1000*table_offset ;
  1147.       table_type = (table_offset > 9) ? (table_offset-9) : 0 ;
  1148.       new_numbers[old_number] = (short)++(tcount[table_type]) ;
  1149.       }
  1150.    point = *start ;
  1151.    free_spot(start) ;
  1152.    return new_numbers ;
  1153. }
  1154.  
  1155. /*=============================================================*/
  1156. /*=============================================================*/
  1157.  
  1158. int adjust_table_numbers(new_numbers, dangling)
  1159. short *new_numbers ;
  1160. int dangling ;
  1161. {
  1162.    char counter[5] ;
  1163.    int old_number ;
  1164.    int old_type ;
  1165.    char *tbl ;
  1166.    int table_offset ;
  1167.    spot start = alloc_spot(1) ;
  1168.    
  1169.    *start = point ;
  1170.    point = 0 ;
  1171.    while (search(1,"(Table "))
  1172.       {
  1173.       grab(point,point+4,counter) ;
  1174.       tbl = index(table_ID_letters,counter[0]) ;
  1175.       if (tbl)
  1176.      table_offset = 1000*(tbl-table_ID_letters) ;
  1177.       else
  1178.      table_offset = 0 ;
  1179.       old_number = strtoi(counter+1,10) + table_offset ;
  1180.       old_type = (counter[0] >= '0' && counter[0] <= '9') ? 0 : counter[0] ;
  1181.       if (old_number > 0)
  1182.      {
  1183.      delete(point,point+4) ;
  1184.      if (old_type)
  1185.         bprintf("%c%03d",old_type,new_numbers[old_number]%1000) ;
  1186.      else
  1187.         bprintf("%04d",new_numbers[old_number]) ;
  1188.      }
  1189.       }
  1190.    point = 0 ;
  1191.    while (re_search(1,"[, \t]%#[0-9CFMP][0-9][0-9][0-9]"))
  1192.       {
  1193.       grab(point-4,point,counter) ;
  1194.       tbl = index(table_ID_letters,counter[0]) ;
  1195.       if (tbl)
  1196.      table_offset = 1000*(tbl-table_ID_letters) ;
  1197.       else
  1198.      table_offset = 0 ;
  1199.       old_number = strtoi(counter+1,10) + table_offset ;
  1200.       old_type = (counter[0] >= '0' && counter[0] <= '9') ? 0 : counter[0] ;
  1201.       if (old_number > 0)
  1202.      {
  1203.      if (new_numbers[old_number])
  1204.         {
  1205.         delete(point-4,point) ;
  1206.         if (old_type)
  1207.            bprintf("%c%03d",old_type,new_numbers[old_number]) ;
  1208.         else
  1209.            bprintf("%04d",new_numbers[old_number]) ;
  1210.         }
  1211.      else /* dangling xref */
  1212.         {
  1213.         dangling++ ;
  1214.         point -= 4 ;
  1215.         stuff("?") ;
  1216.         point += 4 ;
  1217.         }
  1218.      }
  1219.       }
  1220.    point = *start ;
  1221.    free_spot(start) ;
  1222.    return dangling ;
  1223. }
  1224.  
  1225. /*=============================================================*/
  1226. /*=============================================================*/
  1227.  
  1228. int get_list_file(list_file)
  1229. char *list_file ;
  1230. {
  1231.    char abs_filename[FNAMELEN] ;
  1232.    strcpy(abs_filename,list_file) ;
  1233.    absolute(abs_filename) ;
  1234.    return find_it(abs_filename,1) ;
  1235. }
  1236.  
  1237. /*=============================================================*/
  1238. /*=============================================================*/
  1239.  
  1240. command renumber_tables()
  1241. {
  1242.    short *new_numbers ;
  1243.    int num_tables ;
  1244.    int dangling ;
  1245.    int i ;
  1246.    
  1247.    for (i = 0 ; list_files[i] ; i++)
  1248.       {
  1249.       if (get_list_file(list_files[i]) == 0)
  1250.      {
  1251.      say("Renumber Pass 1: numbering unnumbered tables (%s)",
  1252.          list_files[i]) ;
  1253.      fix_unnumbered_tables() ;
  1254.      }
  1255.       else
  1256.      say("Renumber Pass 1: forced to skip %s") ;
  1257.       }
  1258.    num_tables = 1000*strlen(table_ID_letters) ;
  1259.    new_numbers = (short*)malloc(num_tables*sizeof(short)) ;
  1260.    if (!new_numbers)
  1261.       {
  1262.       say("Out of memory!") ;
  1263.       return ;
  1264.       }
  1265.    for (i = 0 ; i < num_tables ; i++)
  1266.       new_numbers[i] = 0 ;
  1267.    for (i = 0 ; list_files[i] ; i++)
  1268.       {
  1269.       if (get_list_file(list_files[i]) == 0)
  1270.      {
  1271.      say("Renumber Pass 2: gathering table numbers (%s)",
  1272.          list_files[i]) ;
  1273.      gather_table_numbers(new_numbers) ;
  1274.      }
  1275.       else
  1276.      say("Renumber Pass 2: forced to skip %s") ;
  1277.       }
  1278.    dangling = 0 ;
  1279.    for (i = 0 ; list_files[i] ; i++)
  1280.       {
  1281.       if (get_list_file(list_files[i]) == 0)
  1282.      {
  1283.      say("Renumber Pass 3: adjusting table numbers (%s)",
  1284.          list_files[i]) ;
  1285.      dangling = adjust_table_numbers(new_numbers,dangling) ;
  1286.      }
  1287.       else
  1288.      say("Renumber Pass 3: forced to skip %s") ;
  1289.       }
  1290.    free(new_numbers) ;
  1291.    if (dangling)
  1292.       say("%d dangling cross-references, search for '#?'",dangling) ;
  1293.    else
  1294.       say("Done") ;
  1295. }
  1296.  
  1297. /*=============================================================*/
  1298. /*=============================================================*/
  1299.  
  1300. command make_distribution()
  1301. {
  1302.    int i ;
  1303.    
  1304.    for (i = 0 ; list_files[i] ; i++)
  1305.       {
  1306.       /* switch to proper buffer, or load if not yet in a buffer */
  1307.       if (get_list_file(list_files[i]) == 0)
  1308.      {
  1309.      say("Setting divider lines (%s)",list_files[i]) ;
  1310.      point = size() ;
  1311.      while (point > 0)
  1312.         if (!number_one_int())
  1313.            break ;
  1314.      }
  1315.       }
  1316.    renumber_tables() ;
  1317.    save_all_buffers() ;
  1318.    say("Ready for distribution") ;
  1319.    point = 0 ;
  1320.    /* !!! should also split main list automatically */
  1321. }
  1322.  
  1323. /*=============================================================*/
  1324. /*=============================================================*/
  1325.  
  1326. void find_table_counter()
  1327. {
  1328.    save_var point = (size() > 10000) ? size() - 10000 : 0 ;
  1329.  
  1330.    search(1,"Highest Table Number = ") ;
  1331.    table_counter = alloc_spot(1) ;
  1332. }
  1333.  
  1334. /*=============================================================*/
  1335. /* Put the current buffer into IntList major mode           */
  1336. /*=============================================================*/
  1337.  
  1338. command intlist_mode()
  1339. {
  1340.    mode_keys = intlist_tab ;
  1341.    intlist_tab[')'] = intlist_tab[']'] = (short) show_matching_delimiter;
  1342.    delete_hacking_tabs = 0 ;
  1343.    major_mode = strsave("IntList") ;
  1344.    make_mode() ;
  1345.    auto_indent = 0 ;
  1346.    margin_right = 79 ;
  1347.    want_backups = 1 ;
  1348.    undo_size = 100000 ;     /* less than default 500,000 since list is so big */
  1349.    find_table_counter() ;
  1350. }
  1351.  
  1352. when_loading()
  1353. {
  1354.    char *curbuf ;
  1355.  
  1356.    want_backups = want_backups.default = 1 ;
  1357.    strcpy(backup_name,"%pbak/%b%e") ;        /* put backups in BAK subdir */
  1358.    one_window() ;
  1359.    intlist_mode() ;
  1360.    if (exist("interrup.1st"))
  1361.       {
  1362.       curbuf = bufname ;
  1363.       bufname = "interrup.1st" ;
  1364.       intlist_mode() ;
  1365.       bufname = curbuf ;
  1366.       }
  1367. /* Epsilon v6.0+ */
  1368.    strcpy(mode_end," %d%p %S") ;
  1369. }
  1370.  
  1371. /*=============================================================*/
  1372. /* automagically switch into interrupt list mode on .LST and .1ST files */
  1373.  
  1374. suffix_lst()   { intlist_mode(); }
  1375. suffix_1st()   { intlist_mode(); }
  1376.  
  1377.  
  1378.